<?php

namespace App\Service\VendorClient\Shophnsm;

use App\Service\Code\Normal;
use App\Service\BaseService;
use Service\AppService\IdService;
use App\Service\TaskServer\TaskWorker;
use App\Model\PssModel\ServiceConfig;
use Hyperf\Utils\Coroutine;
use Hyperf\Utils\WaitGroup;

/**
 * 海南商免科技供应商SDK
 * @author hj
 */
class ShophnsmApiClient extends BaseService {
    //供应商编号
    const SUPPLIER_CODE = 'shophnsm';

    //配置文件
    private $config = [];

    public function __construct($apiBody = []) {
        $this->config = $apiBody;
    }

    /**
     * 创建订单
     * @param array $params
     * @return array
     */
    public function createOrder($param = []) {
        if (empty($param['supplierOrder']) || empty($param['orderGoods']) || empty($param['order']) || empty($param['binfo'])) {
            return Normal::returnCode(Normal::FAIL, "except param supplierOrder or orderGoods or order or binfo");
        }
        $orderInfo = $param['supplierOrder'];
        $goodsList = $param['orderGoods'];
        $order     = $param['order'];
        $binfo     = $param['binfo'];
        $order_sn  = $orderInfo['supplier_dsn'];
        //支付流水号
        $pay_sn = $order['paySerial'] ?? $orderInfo['pay_sn'];
        //订单时间
        $order_time = $orderInfo['cd'] ? date('Y-m-d H:i:s', $orderInfo['cd']) : date('Y-m-d H:i:s', time());
        //支付时间
        $pay_time = isset($order['payTime']) && !empty($order['payTime']) ? date('Y-m-d H:i:s', $order['payTime']) : date('Y-m-d H:i:s', time());
        //运费分摊
        $deliver_money = $orderInfo['deliver_money'];
        //下单支付的时候支付信息
        $apply_extends = @json_decode($orderInfo['apply_extends'], true);

        //判断支付方式是否存在
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $payCommanyCode = $order['payCommanyCode'] ?? $payCommanyCode;
        $payWayInfo     = ServiceConfig::instance()->getConfigByEventsValue(self::SUPPLIER_CODE, ServiceConfig::TYPE_PAY, $payCommanyCode, false);
        if (empty($payWayInfo)) {
            return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$payCommanyCode}】未映射，请联系管理员处理");
        }
        //获取下单商品信息
        $palceOrderGoods    = [];
        $totalGoodsMoney    = '0.00';
        $goodsTotalMoney    = '0.00';
        $goodsTotalMoneyNot = '0.00';
        $wayTaxFee          = '0.00';
        foreach ($goodsList as $key => $item) {
            $tax_rate         = bcadd('1', (string)$item['tax_rate'], 4);
            $price            = $item['price'];
            $spec_num         = $item['spec_num'];
            $quantity         = $item['quantity'];
            $supplier_skucode = $item['supplier_skucode'];
            $goods_type       = $item['goods_type'];
            //实际购买数量(下单数量 X 起售数量)
            $buyAcount = $spec_num * $quantity;
            if ($key == 0) {
                $singleDeliveryMoney = bcdiv((string)$deliver_money, (string)$quantity, 3);
                $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney, (string)100, 1);
                $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100, 2);
                $price               = bcadd((string)$price, (string)$singleDeliveryMoney, 2);
            }

            //不含税价格
            $singleGoodsPrice = bcdiv((string)$price, (string)$tax_rate, 3);
            $singleGoodsPrice = bcmul((string)$singleGoodsPrice, (string)100, 1);
            $singleGoodsPrice = bcdiv((string)ceil($singleGoodsPrice), (string)100, 2);
            //商品不含税总价
            $goodsTotalPrice = bcmul((string)$singleGoodsPrice, (string)$quantity, 2);
            //含税总价
            $goodsTotalPriceTax = bcmul((string)$price, (string)$quantity, 2);
            //税费
            $tax    = bcsub((string)$price, (string)$singleGoodsPrice, 2);
            $taxAll = bcmul((string)$tax, (string)$quantity, 2);

            //判断是不是保税订单
            $taxAll = $goods_type == 1 ? $taxAll : 0;
            //不含税总金额
            $goodsTotalMoneyNot = bcadd((string)$goodsTotalMoneyNot, (string)$goodsTotalPrice, 2);
            //含税总金额
            $goodsTotalMoney = bcadd((string)$goodsTotalMoney, (string)$goodsTotalPriceTax, 2);
            //总税费
            $wayTaxFee = bcadd((string)$wayTaxFee, (string)$taxAll, 2);
            //下单商品组
            $goodsInfo         = [
                'SKUID'       => $item['supplier_skucode'],//商品编码 订单内必须唯一
                'SKUNAME'     => $item['goods_name'],//商品名称
                'SUPPLIERSKU' => $item['supplier_skucode'],//备案料号
                'QTY'         => (int)$buyAcount,//数量
                'TAXEDPRICE'  => $price,//含税价
                'NOTAXPRICE'  => $singleGoodsPrice,//未含税价
                'SINGLETAX'   => $tax,//单个商品税款，不用乘以数量
            ];
            $palceOrderGoods[] = $goodsInfo;
        }
        $couponFee    = $goodsTotalMoney > $orderInfo['real_total_money'] ? bcsub($goodsTotalMoney, $orderInfo['real_total_money'], 2) : '0.00';
        $requestParam = [
            'ORDERNO'               => $order_sn,//订单号，唯一性不可重复
            'GMORDERNO'             => $order_sn,//海关单号，发到海关的支付支付单号，后续出库以此为单号
            'PAYTYPE'               => (string)$payWayInfo['service_third_value'],//支付方式
            'PAYORDERID'            => $order['paySerial'] ?? $apply_extends['paySerial'],//支付交易流水号
            'BUYTIME'               => $order_time,//下单时间
            'PAYTIME'               => $pay_time,//支付时间
            'RECEIVER_ID_NO'        => $orderInfo['buyer_idcard'],//购买人身份证号,//收件人身份证
            'RECEIVER_NAME'         => $orderInfo['receive_name'],//收件人
            'RECEIVER_PROVINCE'     => $orderInfo['province'],//收件省份
            'RECEIVER_CITY'         => $orderInfo['city'],//收件城市
            'RECEIVER_DISTRICT'     => $orderInfo['district'],//收件区域
            'RECEIVER_TEL'          => $orderInfo['recveive_phone'],//收件人电话
            'RECEIVER_SHORTADDRESS' => $orderInfo['receive_address'],//收件地址
            'BUYER_NAME'            => $orderInfo['buyer_realname'],//订购人
            'BUYER_ID_TYPE'         => '1',//1 身份证
            'BUYER_ID'              => $orderInfo['buyer_idcard'],//1 订购证件号码
            'GOODS_FEE'             => $goodsTotalMoneyNot,//货物总值 不含税
            'TAX_FEE'               => $wayTaxFee,//税款
            'TRANSPORT_FEE'         => '0.00',//运费
            'INSURED_FEE'           => '0.00',//保价费
            'DISCOUNT'              => $couponFee,//折扣 大于等于0
            'ACTUAL_PAID'           => $orderInfo['real_total_money'],//实际支付 货物总值+税款+运费+保价费-折扣=实际支付
            'EBPCODE'               => $order['enterpriseNum'] ?? $apply_extends['enterpriseNum'],//电商平台代码
            'EBPNAME'               => $order['enterpriseName'] ?? $apply_extends['enterpriseName'],//电商平台名称

            'ESHOP_ENT_CODE' => $this->config['eshop_ent_code'] ?? '',//电商企业代码
            // 'MALL_ID' => '0.00',// 拼多多店铺ID
            'ESHOP_ENT_NAME' => $this->config['eshop_ent_name'] ?? '',// 电商企业名称
            'SKUITEMS'       => $palceOrderGoods,//商品明细
        ];
        $data         = [
            'method' => 'createOrder',
            'data'   => [
                'IDCODE' => $this->config['idcode'],
                'ORDERS' => [$requestParam]
            ],
        ];
        $res          = $this->execute($data);
        //模拟
        if ($res['code'] == Normal::SUC) {
            return Normal::returnCode(Normal::SUC, "订单推送成功", [
                'thirdpart_order_sn' => $res['data']['data']['out_trade_no']
            ]);
        }
        return $res;
    }

    /**
     * 获取取消订单
     */
    public function cancelOrder($params = []) {
        $res = Normal::returnCode(Normal::FAIL, '为申请任何订单退款');
        foreach ($params['orderGoods'] as $item) {
            $data = [
                'method' => 'cancelOrder',
                'data'   => [
                    'out_trade_no'  => $params['supplierOrder']['thirdpart_order_sn'],
                    'sku_id'        => $item['supplier_skucode'],
                    'refund_reason' => $params['order']['exceptReason'] ?? '申请订单退款作废,不要了',
                ],
            ];
            $res  = $this->execute($data);
        }
        return $res;
    }

    /**
     * 商品列表 只维护价格和库存
     * 请求域名    https://yonbip-core3.diwork.com/iuap-api-gateway
     * 请求地址    /yonbip/digitalModel/product/list
     */
    public function queryGoodsList($param = []) {
        $allClassRes = $this->queryCategory();
        if ($allClassRes['code'] != Normal::SUC) {
            return $allClassRes;
        }
        $allClass = $allClassRes['data'];
        $reqParam = [
            'method' => 'queryGoods',
            'data'   => [
                'page'      => $param['page'] ?? 1,
                'page_size' => isset($param['limit']) && !empty($param['limit']) ? $param['limit'] > 30 ? 30 : $param['limit'] : 30,
                // 'category_id'  => 11,//分类id
            ]
        ];
        $res      = $this->execute($reqParam);
        if ($res['code'] != Normal::SUC) {
            return $res;
        }
        if (!isset($res['data']['data']['list']) || empty($res['data']['data']['list'])) {
            $result = ['total' => 0, 'data' => [], 'hasPage' => 0];
            return Normal::returnCode(Normal::SUC, '获取成功', $result);
        }
        $newData = [];
        foreach ($res['data']['data']['list'] as $v) {
            $categoryIdStr = trim($v['category_id'], ',');
            if ($categoryIdStr) {
                $categoryIdArr  = explode(',', $categoryIdStr);
                $lastCategoryId = end($categoryIdArr);
                $className      = $allClass[$lastCategoryId] ?? '暂无';
            } else {
                $className = '暂无';
            }
            if (!isset($v['spec_data']) || empty($v['spec_data'])) {
                continue;
            }
            $specData = reset($v['spec_data']);
            if (
                !isset($specData['sku_id']) ||
                !isset($specData['sku_no']) ||
                !isset($specData['tax_rate']) ||
                !isset($specData['taxation_price']) ||
                !isset($specData['shop_price']) ||
                !isset($specData['sku_name']) ||
                !isset($specData['price']) ||
                !isset($specData['stock']) ||
                !isset($specData['is_free_shipping'])) {
                continue;
            }
            $attr    = $specData['goods_attr_format'] ?? [];
            $batchNo = '基准批次';
            if ($attr) {
                foreach ($attr as $item) {
                    if (self::isDateTime($item['attr_value_name'])) {
                        $batchNo = $item['attr_value_name'];
                        break;
                    }
                }
            }
            $newData[] = [
                'goods_id'         => $v['goods_id'],//商品ID
                'unit'             => '暂无',//主计量单位名称
                'brand'            => $v['label_name'] ?? '',//品牌名称
                'sku_id'           => $specData['sku_id'],//skuid 下单用
                'sku_no'           => $specData['sku_no'],//料号（商品编码）
                'tax_rate'         => $specData['tax_rate'],//税率
                'taxation_price'   => $specData['taxation_price'],//税费
                'shop_price'       => $specData['shop_price'],//精英折扣价(结算基准价)  供货价
                'sku_name'         => $specData['sku_name'],//sku商品名称
                'price'            => $specData['price'],//销售价格
                'spec_num'         => 1,//单规格
                'stock'            => $specData['stock'],//库存
                'batch_no'         => $batchNo,//批次/效期
                'is_free_shipping' => $specData['is_free_shipping'],//是否包邮，1=是，0=不是
                'barcode'          => $v['barcode'],//商品条形码
                'is_limit'         => $v['is_limit'],//商品是否限购(0=否，1=是)
                'max_buy'          => $v['max_buy'],//限购数
                'min_buy'          => $v['min_buy'],//起购数
                'goods_name'       => $v['goods_name'] ?? '',//名称
                'weight'           => $v['weight'] ?? '0',//重量
                'goods_image'      => $v['goods_image'] ?? '',//商品主图
                'description'      => $v['goods_content'] ?? '',//商品详情
                'class_name'       => $className,//商品分类名称
            ];
        }
        // echo json_encode($newData, 320);die;
        $result = ['total' => count($newData), 'data' => $newData];
        return Normal::returnCode(Normal::SUC, '获取成功', $result);
    }

    /**
     * 查询指定商品详情
     */
    public function queryGoodsDetail(array $sku_id) {
        $reqParam = [
            'method' => 'queryGoodsDetail',
            'data'   => [
                'sku_id' => implode(',', $sku_id),//商品sku_id（支持单个和多个获取，示例：5298,5299）
            ]
        ];
        return $this->execute($reqParam);
    }

    /**
     * 获取所有分类
     */
    public function queryCategory() {
        $reqParam = [
            'method' => 'queryCategory',
            'data'   => [
                // 'level' => 3,//等级分类，默认返回3级分类
            ]
        ];
        $res      = $this->execute($reqParam);
        if ($res['code'] != Normal::SUC) {
            return $res;
        }
        if (!isset($res['data']['data']) || empty($res['data']['data'])) {
            // return Normal::returnCode(Normal::FAIL, '商品分类列表为空');
            return Normal::returnCode(Normal::SUC, '获取成功', []);
        }
        $allClass = [];
        foreach ($res['data']['data'] as $v) {
            $allClass[$v['category_id']] = $v['category_name'];
            if (isset($v['child_list']) && !empty($v['child_list'])) {
                foreach ($v['child_list'] as $vv) {
                    $allClass[$vv['category_id']] = $vv['category_name'];
                    if (isset($vv['child_list']) && !empty($vv['child_list'])) {
                        foreach ($vv['child_list'] as $vvv) {
                            $allClass[$vvv['category_id']] = $vvv['category_name'];
                        }
                    }
                }
            }
        }
        return Normal::returnCode(Normal::SUC, '获取成功', $allClass);
    }

    /**
     * 签名
     * @param $data
     * @return string
     */
    public function sign($data) {
        ksort($data);
        $stringA = '';
        foreach ($data as $k => $v) {
            if (!empty($v)) {
                $stringA .= $k . '=' . $v . '&';
            }
        }
        $stringSignTemp = $stringA . 'secret=' . $this->config['appSecret'];
        return strtoupper(md5($stringSignTemp));
    }

    /**
     * 生成不大于32位随机数
     * @param int $length 生成随机数的长度
     */
    public function randomKeys($length = 32) {
        $pattern = '1234567890abcdefghijklmnopqrstuvwxyz';
        $key     = '';
        for ($i = 0; $i < $length; $i++) {
            $key .= $pattern{mt_rand(0, 35)};
        }
        return $key;
    }

    /**
     * 判断字符串是否是指定格式的日期
     */
    public static function isDateTime($dateTime, $formats = ['Y-m-d', 'Y/m/d', 'Y-m-d H:i:s', 'Ymd', 'Y-m']) {
        $unixTime = strtotime($dateTime);
        if (!$unixTime) {
            //strtotime转换不对，日期格式显然不对。
            return false;
        }
        //校验日期的有效性，只要满足其中一个格式就OK
        foreach ($formats as $format) {
            if (date($format, $unixTime) == $dateTime) {
                return true;
            }
        }
        return false;
    }

    /**
     * CURL请求
     * @param $params
     * @return array
     */
    public function execute($param = []) {
        $method = $param['method'];
        $data   = $param['data'];
        if (!isset($this->config[$method])) {
            return Normal::returnCode(Normal::FAIL, "请求路由未设置");
        }
        // if (empty($param['data'])) {
        //     return Normal::returnCode(Normal::FAIL, "数据不能为空");
        // }
        $url = $this->config['baseUrl'] . $this->config[$method];
        if (empty($url)) {
            return Normal::returnCode(Normal::FAIL, "接口地址不能为空");
        }
        $commonData = [
            'timestamp' => time(),
            'nonce_str' => $this->randomKeys(),//不大于32位随机数
        ];
        $pushData   = array_merge($commonData, $param['data']);
        $sign       = $this->sign($pushData);
        $parameter  = [
            [
                'tag'    => self::SUPPLIER_CODE . '_' . $method,
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $url,
                'data'   => $pushData,
                'method' => 'post',
                'format' => 'json',
                'header' => [
                    "Content-Type: application/json",
                    "sign: {$sign}",
                    "authorization: {$this->config['appKey']}"
                ],
            ],
        ];
        if (in_array($method, ['queryGoods', 'queryCategory', 'queryGoodsDetail'])) {
            $resTask = TaskWorker::instance()->addTask($parameter, 'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask = current($resTask);
        $result  = @json_decode($resTask['response']['result'], true);
        if (isset($result['code']) && $result['code'] == 1) {
            return Normal::returnCode(Normal::SUC, "请求成功", $result);
        } else {
            $msg = $result['msg'] ?? '请求失败';
            return Normal::returnCode(Normal::FAIL, $msg);
        }
    }

}